#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<iostream>
using namespace std;

// 静态成员定义
int MainWindow::click_width=0;//记录鼠标点击的位置
int MainWindow::click_height=0;
int MainWindow::release_width=0;//记录鼠标释放的位置
int MainWindow::release_height=0;
int MainWindow::valve = 0;//控制画笔的撤回功能

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setWindowTitle("图像处理实验  黎泉林&莫文青");

    //Qspinbox与Qslider的数据连接，使他们一起变化
    void(QSpinBox::  * spSignal)(int)=&QSpinBox::valueChanged;
    connect(ui->spinBox,spSignal,ui->horizontalSlider,&QSlider::setValue);
    connect(ui->horizontalSlider,&QSlider::valueChanged,ui->spinBox,&QSpinBox::setValue);

    void(QSpinBox::  * spSignal_2)(int)=&QSpinBox::valueChanged;
    connect(ui->spinBox_2,spSignal_2,ui->horizontalSlider_2,&QSlider::setValue);
    connect(ui->horizontalSlider_2,&QSlider::valueChanged,ui->spinBox_2,&QSpinBox::setValue);
    ui->spinBox_2->setValue(15);

    void(QSpinBox::  * spSignal_3)(int)=&QSpinBox::valueChanged;
    connect(ui->spinBox_3,spSignal_3,ui->horizontalSlider_3,&QSlider::setValue);
    connect(ui->horizontalSlider_3,&QSlider::valueChanged,ui->spinBox_3,&QSpinBox::setValue);

    void(QSpinBox::  * spSignal_4)(int)=&QSpinBox::valueChanged;
    connect(ui->spinBox_4,spSignal_4,ui->horizontalSlider_4,&QSlider::setValue);
    connect(ui->horizontalSlider_4,&QSlider::valueChanged,ui->spinBox_4,&QSpinBox::setValue);

    void(QSpinBox::  * spSignal_5)(int)=&QSpinBox::valueChanged;
    connect(ui->spinBox_5,spSignal_5,ui->horizontalSlider_5,&QSlider::setValue);
    connect(ui->horizontalSlider_5,&QSlider::valueChanged,ui->spinBox_5,&QSpinBox::setValue);

    void(QSpinBox::  * spSignal_6)(int)=&QSpinBox::valueChanged;
    connect(ui->spinBox_6,spSignal_6,ui->horizontalSlider_6,&QSlider::setValue);
    connect(ui->horizontalSlider_6,&QSlider::valueChanged,ui->spinBox_6,&QSpinBox::setValue);
     ui->spinBox_6->setValue(125);
}

MainWindow::~MainWindow()
{
    delete ui;
}

//鼠标滚轮
void MainWindow::wheelEvent(QWheelEvent *ev)
{
    if(Arbitrary_scaling_valve % 2 != 0)
    {
    //滚轮上滚
    if(ev->delta()>0)
    {
      multiple += 0.05;//默认为1，每滚一次加0.1
      myimg.Arbitrary_scaling(myimg_2,multiple);//放大
    }
    //鼠标下滚
    if(ev->delta()<0)
    {
         multiple-=0.05;//默认为1，每滚一次减0.1
         if(multiple>0.3)//设定最小缩小因数
          myimg.Arbitrary_scaling(myimg_2,multiple);//缩小
    }

  //下面几句函数是为了将内存中的图像数据显示出来，并使label控件随着图片大小而改变
   QImage a(myimg_2.GetWidth(),myimg_2.GetHeight(),QImage::Format_ARGB32);
   myimg_2.Secon_to_First(a.bits());
   ui->label->setPixmap(QPixmap::fromImage(a));
   ui->label->resize(myimg_2.GetWidth(),myimg_2.GetHeight());
    }
}

//鼠标移动
void MainWindow::mouseMoveEvent(QMouseEvent *ev)
{
    if(paintbrush_valve % 2 != 0)//阈值，用来控制画笔的开关
    {
         {

        myimg.Paintbrush(ev->y()-20,ev->x(),paintbrush_R,paintbrush_B,paintbrush_G,paintbrush_size);

        QImage a(myimg.GetWidth(),myimg.GetHeight(),QImage::Format_ARGB32);
        myimg.Secon_to_First(a.bits());
        ui->label->setPixmap(QPixmap::fromImage(a));
         }

         if(valve % 2 != 0)//鼠标点击会使valve加一，这样画笔的每一笔都会保存一次
         {
             Cancel_Image();//保存图像数据

             MainWindow::valve++;//阈值，用来控制画笔的保存功能
         }
    }

    //鼠标滑动区域特效，与画笔不能同时生效
    else if(click_width>=0&&click_width<myimg.GetWidth()&&click_height>0&&click_height<myimg.GetHeight())//启动条件
    {
        int y1=click_height;
        int x1=click_width;
        int y2=ev->y();
        int x2=ev->x();
        //点从右下到左上
            if(x2<x1&&y2<y1)
            {
                int temp;
                temp=x1;
                x1=x2;
                x2=temp;

                temp=y1;
                y1=y2;
                y2=temp;
            }

            //点从左下到右上
            if(x1<x2&&y1>y2)
            {
                int temp;
                temp=y1;
                y1=y2;
                y2=temp;
            }

            //点从右上到左下
            if(x1>x2&&y1<y2)
            {
                int temp;
                temp=x1;
                x1=x2;
                x2=temp;
            }

            //处理越界
            if(x1<0)x1=0;
            if(x1>myimg.GetWidth()-1)x1=myimg.GetWidth()-1;
            if(y1<0)y1=0;
            if(y1>myimg.GetHeight()-1)y1=myimg.GetHeight()-1;

            if(x2<0)x2=0;
            if(x2>myimg.GetWidth()-1)x2=myimg.GetWidth()-1;
            if(y2<20)y2=20;//20是移动坐标y轴的偏移量（窗口顶部）
            if(y2>myimg.GetHeight()+19)y2=myimg.GetHeight()+19;

               QImage a(myimg.GetWidth(),myimg.GetHeight(),QImage::Format_ARGB32);

               //修改Qimage的透明度A，而不改变原有数据，就能达到选中区域特效的效果，Qimage一个像素值有四个通道RBGA，A控制图片的透明度
                myimg.Secon_to_First(a.bits());
                unsigned char* da=a.bits();
                for(int i=y1;i<y2-20;i++)
               {
                     for(int j=x1*4;j<x2*4;j+=4)
                    {
                       da[i*myimg.GetWidth()* 4+j+3]=100;//100是透明度，0最低，255最高
                     }
               }

                ui->label->setPixmap(QPixmap::fromImage(a));
                ui->label->resize(myimg.GetWidth(),myimg.GetHeight());

       }

}


//撤销功能，保存此时的图像；每次进行图片处理操作时都会自动调用这个函数
void MainWindow::Cancel_Image()
{
    //head：最新保存的图片所在的位置；p：显示的图片所在的位置；tail：数组中最旧的那张图片所在的位置
    cancel_head=cancel_p;//将p赋为给head是因为使用了撤销功能后p是比head小的，此时进行某个图像处理功能，应当舍弃掉p之前的数据
    cancel_head++;//从cancel_arr[1]开始储存数据，cancel_arr[0]用来存空白图像；
    if(cancel_head == cancel_quantity)cancel_head = 0;//cancel_quantity是数组的长度；
    if(cancel_head==cancel_tail)cancel_tail++;//tail是可以撤回的图片中最后一张，tail+1代表此时最后一张被覆盖了。这样做可以重复利用数组
    if(cancel_tail==cancel_quantity)cancel_tail = 0;

    cancel_arr[cancel_head]=myimg;//保存副本
    cancel_p=cancel_head;
}

//梯度化
void MainWindow::on_pushButton_3_clicked()
{
    if(sharpen_valve%2==0)//调用一次打开，再调用一次取消
    {
    sharpen_myimg=myimg;//拷贝副本
    myimg.sharpen();


    }
    else myimg=sharpen_myimg;

     Cancel_Image();
    QImage a(myimg.GetWidth(),myimg.GetHeight(),QImage::Format_ARGB32);
    myimg.Secon_to_First(a.bits());
    ui->label->setPixmap(QPixmap::fromImage(a));
    sharpen_valve++;
 ui->label->resize(myimg.GetWidth(),myimg.GetHeight());
}

//灰度化
void MainWindow::on_pushButton_4_clicked()
{
    if(Grey_scale_valve%2==0)
    {
    Grey_scale_myimg=myimg;//拷贝副本
    myimg.Grey_scale();

    Cancel_Image();
    }
    else myimg=Grey_scale_myimg;

    QImage a(myimg.GetWidth(),myimg.GetHeight(),QImage::Format_ARGB32);
    myimg.Secon_to_First(a.bits());
    ui->label->setPixmap(QPixmap::fromImage(a));
    Grey_scale_valve++;
     ui->label->resize(myimg.GetWidth(),myimg.GetHeight());
}

//打开图片文件
void MainWindow::on_actionopen_2_triggered()
{

    QString filename;
    filename=QFileDialog::getOpenFileName(this,
                                        tr("选择图像"),
                                        "",
                                        tr("Images (*.png *.bmp *.jpg *.tif *.GIF )"));//可打开的文件类型
  if(!filename.isEmpty())//判断文件路径是否为空，防止程序崩溃
  {
       if(myimg.ReadBMP(filename))
       {
        ui->label->resize(myimg.GetWidth(),myimg.GetHeight());
        QImage a(myimg.GetWidth(),myimg.GetHeight(),QImage::Format_ARGB32);
        myimg.Secon_to_First(a.bits());
        ui->label->setPixmap(QPixmap::fromImage(a));
         Cancel_Image();
       }
  }
}

//保存文件
void MainWindow::on_actionsave_2_triggered()
{
    QString filename1 = QFileDialog::getSaveFileName(this,tr("请选择保存路径"),"",tr("Images ( *.bmp *.png *.jpg)")); //选择路径
   if(!filename1.isEmpty())
   {
    myimg.WriteBMP(filename1);
   }
}

//边框提取
void MainWindow::on_pushButton_clicked()
{
    if(sharpenre_valve%2==0)
    {
    sharpenre_myimg=myimg;//拷贝副本
    myimg.sharpenre();
    Cancel_Image();
    }
    else myimg=sharpenre_myimg;


    sharpenre_valve++;
    QImage a(myimg.GetWidth(),myimg.GetHeight(),QImage::Format_ARGB32);
    myimg.Secon_to_First(a.bits());
    ui->label->setPixmap(QPixmap::fromImage(a));
     ui->label->resize(myimg.GetWidth(),myimg.GetHeight());
}

//顺时针90°
void MainWindow::on_pushButton_5_clicked()
{
    myimg.Rotate(90);

    Cancel_Image();
    QImage a(myimg.GetWidth(),myimg.GetHeight(),QImage::Format_ARGB32);
    myimg.Secon_to_First(a.bits());
    ui->label->setPixmap(QPixmap::fromImage(a));
     ui->label->resize(myimg.GetWidth(),myimg.GetHeight());
}

//逆时针90°
void MainWindow::on_pushButton_6_clicked()
{
    myimg.Rotate(-90);

    Cancel_Image();
    QImage a(myimg.GetWidth(),myimg.GetHeight(),QImage::Format_ARGB32);
    myimg.Secon_to_First(a.bits());
    ui->label->setPixmap(QPixmap::fromImage(a));
     ui->label->resize(myimg.GetWidth(),myimg.GetHeight());
}

//左右翻转
void MainWindow::on_pushButton_7_clicked()
{
    myimg.Flip(0);

    Cancel_Image();
    QImage a(myimg.GetWidth(),myimg.GetHeight(),QImage::Format_ARGB32);
    myimg.Secon_to_First(a.bits());
    ui->label->setPixmap(QPixmap::fromImage(a));
     ui->label->resize(myimg.GetWidth(),myimg.GetHeight());
}

//上下翻转
void MainWindow::on_pushButton_8_clicked()
{
    myimg.Flip(1);

    Cancel_Image();
    QImage a(myimg.GetWidth(),myimg.GetHeight(),QImage::Format_ARGB32);
    myimg.Secon_to_First(a.bits());
    ui->label->setPixmap(QPixmap::fromImage(a));
     ui->label->resize(myimg.GetWidth(),myimg.GetHeight());
}

//取反
void MainWindow::on_pushButton_2_clicked()
{
    -myimg;

     Cancel_Image();
    QImage a(myimg.GetWidth(),myimg.GetHeight(),QImage::Format_ARGB32);
    myimg.Secon_to_First(a.bits());
    ui->label->setPixmap(QPixmap::fromImage(a));
     ui->label->resize(myimg.GetWidth(),myimg.GetHeight());
}

//锐化
void MainWindow::on_pushButton_11_clicked()
{
   //先创一个Image对象myimg1，将myimg赋给myimg1，然后myimg1边框提取，最后myimg+myimg1就是锐化了
    Image myimg1;
    myimg1=myimg;
    myimg1.sharpenre();
    myimg1.gray2bw(160);//二值化
    for(int i=0;i<myimg.GetHeight();i++)
    {
        for(int j=0;j<myimg.GetWidth()*3;j++)
        {
            myimg.SetDatare(i,j,myimg1.GetData(i,j)/ 20);
        }
    }

     Cancel_Image();
     QImage a(myimg.GetWidth(),myimg.GetHeight(),QImage::Format_ARGB32);
     myimg.Secon_to_First(a.bits());
     ui->label->setPixmap(QPixmap::fromImage(a));
     ui->label->resize(myimg.GetWidth(),myimg.GetHeight());
}

//撤销功能
void MainWindow::on_pushButton_9_clicked()
{
     //p:显示的图片所在的位置，p-1代表图像后撤一步
    if(cancel_p > cancel_tail)
    {
        cancel_p--;
    }
    else if((cancel_tail>cancel_head)&&cancel_p<cancel_tail)cancel_p-1==0?(cancel_p=cancel_quantity-1):cancel_p--;

    myimg=cancel_arr[cancel_p];
    QImage a(myimg.GetWidth(),myimg.GetHeight(),QImage::Format_ARGB32);
    myimg.Secon_to_First(a.bits());
    ui->label->setPixmap(QPixmap::fromImage(a));
     ui->label->resize(myimg.GetWidth(),myimg.GetHeight());
      multiple = 1;//撤销缩放功能时用到
}

//取消撤销功能
void MainWindow::on_pushButton_10_clicked()
{
    if(cancel_p < cancel_head)
    {
        cancel_p++;
        myimg=cancel_arr[cancel_p];
        QImage a(myimg.GetWidth(),myimg.GetHeight(),QImage::Format_ARGB32);
        myimg.Secon_to_First(a.bits());
        ui->label->setPixmap(QPixmap::fromImage(a));
         ui->label->resize(myimg.GetWidth(),myimg.GetHeight());
    }

    else if((cancel_tail>cancel_head)&&cancel_p>cancel_head)
    {
        cancel_p + 1==cancel_quantity?(cancel_p=0):cancel_p++;

    myimg=cancel_arr[cancel_p];
    QImage a(myimg.GetWidth(),myimg.GetHeight(),QImage::Format_ARGB32);
    myimg.Secon_to_First(a.bits());
    ui->label->setPixmap(QPixmap::fromImage(a));
     ui->label->resize(myimg.GetWidth(),myimg.GetHeight());
      ui->label->resize(myimg.GetWidth(),myimg.GetHeight());
    }
}

//均值滤波
void MainWindow::on_pushButton_12_clicked()
{
    myimg.MeanFilter(ui->widget->getNum());

    Cancel_Image();
    QImage a(myimg.GetWidth(),myimg.GetHeight(),QImage::Format_ARGB32);
    myimg.Secon_to_First(a.bits());
    ui->label->setPixmap(QPixmap::fromImage(a));
     ui->label->resize(myimg.GetWidth(),myimg.GetHeight());
}

//马赛克
void MainWindow::on_pushButton_13_clicked()
{
    myimg.mosaic(click_width,click_height,release_width,release_height);//这几个变量由鼠标事件获取

    Cancel_Image();
    QImage a(myimg.GetWidth(),myimg.GetHeight(),QImage::Format_ARGB32);
    myimg.Secon_to_First(a.bits());
    ui->label->setPixmap(QPixmap::fromImage(a));
     ui->label->resize(myimg.GetWidth(),myimg.GetHeight());
}

//剪切
void MainWindow::on_pushButton_14_clicked()
{
    myimg.Cut(click_width,click_height,release_width,release_height);//这几个变量由鼠标事件获取

    Cancel_Image();

    QImage a(myimg.GetWidth(),myimg.GetHeight(),QImage::Format_ARGB32);
    myimg.Secon_to_First(a.bits());
    ui->label->setPixmap(QPixmap::fromImage(a));
     ui->label->resize(myimg.GetWidth(),myimg.GetHeight());
}

//中值滤波
void MainWindow::on_pushButton_15_clicked()
{
    myimg.MedianFilter(ui->widget->getNum());

    Cancel_Image();
    QImage a(myimg.GetWidth(),myimg.GetHeight(),QImage::Format_ARGB32);
    myimg.Secon_to_First(a.bits());
    ui->label->setPixmap(QPixmap::fromImage(a));
     ui->label->resize(myimg.GetWidth(),myimg.GetHeight());
}

//更改颜色值R
void MainWindow::on_pushButton_16_clicked()
{
    myimg.ChangeRBG(1,ui->spinBox->value());

    Cancel_Image();
    QImage a(myimg.GetWidth(),myimg.GetHeight(),QImage::Format_ARGB32);
    myimg.Secon_to_First(a.bits());
    ui->label->setPixmap(QPixmap::fromImage(a));
     ui->label->resize(myimg.GetWidth(),myimg.GetHeight());
}

//更改颜色值B
void MainWindow::on_pushButton_17_clicked()
{
    myimg.ChangeRBG(2,ui->spinBox->value());

    Cancel_Image();
    QImage a(myimg.GetWidth(),myimg.GetHeight(),QImage::Format_ARGB32);
    myimg.Secon_to_First(a.bits());
    ui->label->setPixmap(QPixmap::fromImage(a));
     ui->label->resize(myimg.GetWidth(),myimg.GetHeight());
}

//更改颜色值G
void MainWindow::on_pushButton_18_clicked()
{
    myimg.ChangeRBG(3,ui->spinBox->value());

    Cancel_Image();
    QImage a(myimg.GetWidth(),myimg.GetHeight(),QImage::Format_ARGB32);
    myimg.Secon_to_First(a.bits());
    ui->label->setPixmap(QPixmap::fromImage(a));
     ui->label->resize(myimg.GetWidth(),myimg.GetHeight());
}

//更改颜色值RBG
void MainWindow::on_pushButton_19_clicked()
{
    myimg.ChangeRBG(0,ui->spinBox->value());

    Cancel_Image();
    QImage a(myimg.GetWidth(),myimg.GetHeight(),QImage::Format_ARGB32);
    myimg.Secon_to_First(a.bits());
    ui->label->setPixmap(QPixmap::fromImage(a));
     ui->label->resize(myimg.GetWidth(),myimg.GetHeight());
}

//缩放功能阈门开启
void MainWindow::on_pushButton_20_clicked()
{
    Arbitrary_scaling_valve++;
    multiple = 1;
    Cancel_Image();
}

//画笔功能点击一次打开，再点击一次关闭
void MainWindow::on_pushButton_21_clicked()
{
    paintbrush_valve++;
    paintbrush_size=ui->horizontalSlider_2->value();//获取画笔粗细
    paintbrush_R=ui->horizontalSlider_3->value();//获取画笔颜色
    paintbrush_B=ui->horizontalSlider_4->value();
    paintbrush_G=ui->horizontalSlider_5->value();
}

//二值化
void MainWindow::on_pushButton_22_clicked()
{
    myimg.gray2bw(ui->spinBox_6->value());

    Cancel_Image();
    QImage a(myimg.GetWidth(),myimg.GetHeight(),QImage::Format_ARGB32);
    myimg.Secon_to_First(a.bits());
    ui->label->setPixmap(QPixmap::fromImage(a));
     ui->label->resize(myimg.GetWidth(),myimg.GetHeight());
}

//缩放功能阀门关闭，缩放每次都是在原图的基础上缩放，所以只有在关闭时才会修改原图的数据
void MainWindow::on_pushButton_23_clicked()
{
    Arbitrary_scaling_valve++;
    myimg=myimg_2;
    Cancel_Image();
}
